﻿using System;
using System.Activities;
using System.Activities.Expressions;
using System.Activities.Statements;
using ActivityLib;

namespace DynamicWorkflow
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //SequenceDynamic();
            //FlowchartDynamic();
            StateMachineDynamic();
            Console.ReadLine();
        }

        /// <summary>
        /// 序列工作流
        /// </summary>
        static void SequenceDynamic()
        {
            Sequence sequence = new Sequence();

            //创建变量
            Variable<int> Target = new Variable<int>();
            Variable<int> Guess = new Variable<int>();
            //序列添加变量
            sequence.Variables.Add(Target);
            sequence.Variables.Add(Guess);

            //随机生成目标值
            var assign = new Assign();
            assign.To = new OutArgument<int>(Target);//指定序列中的变量，并给它赋值
            assign.Value = new InArgument<int>(ctx => new Random().Next(1, 101));
            sequence.Activities.Add(assign);

            var whileSequence = new Sequence();

            //提示：请输入......
            var inputTip = new WriteLine() { Text = "请猜测一个1到100之间的数字：" };
            whileSequence.Activities.Add(inputTip);
            //接收输入
            var input = new GuessInput()
            {
                Text = "动态生成节点演示-Sequence",
                Result = new OutArgument<int>(Guess)
            };
            whileSequence.Activities.Add(input);
            //判断大小
            var ifNode = new If()
            {
                Condition = new InArgument<bool>(ctx => Guess.Get(ctx) < Target.Get(ctx)),
                Then = new WriteLine() { Text = "猜小了，请再猜！" },
                Else = new If()
                {
                    Condition = new InArgument<bool>(ctx => Guess.Get(ctx) > Target.Get(ctx)),
                    Then = new WriteLine() { Text = "猜大了，请再猜！" },
                    Else = new WriteLine() { Text = "恭喜你，猜对了！" }
                }
            };
            whileSequence.Activities.Add(ifNode);
            var doWhile = new DoWhile(ctx => Guess.Get(ctx) != Target.Get(ctx))
            {
                Body = whileSequence,//Condition = Guess != Target
            };
            sequence.Activities.Add(doWhile);
            //启动
            WorkflowInvoker.Invoke(sequence);
        }

        /// <summary>
        /// 流程图工作流
        /// </summary>
        static void FlowchartDynamic()
        {
            Flowchart chart = new Flowchart();
            //创建变量
            Variable<int> Target = new Variable<int>();
            Variable<int> Guess = new Variable<int>();
            //添加变量
            chart.Variables.Add(Target);
            chart.Variables.Add(Guess);
            //活动节点
            var assign = new Assign();
            assign.To = new OutArgument<int>(Target);//指定序列中的变量，并给它赋值
            assign.Value = new InArgument<int>(ctx => new Random().Next(1, 101));
            var assignStep = new FlowStep() { Action = assign };
            var inputTip = new WriteLine() { Text = "请猜测一个1到100之间的数字：" };
            // ExpressionServices.Convert<int>(ctx => Target.Get(ctx)).ToString()
            var tipStep = new FlowStep() { Action = inputTip };
            //接收输入
            var input = new GuessInput()
            {
                Text = "动态生成节点演示-Flowchart",
                Result = new OutArgument<int>(Guess)
            };
            var inputStep = new FlowStep() { Action = input };
            FlowDecision decision = new FlowDecision()
            {
                Condition = ExpressionServices.Convert<bool>(ctx => Guess.Get(ctx) < Target.Get(ctx)),
                True = new FlowStep()
                {
                    Action = new WriteLine() { Text = "猜小了，请再猜！" },
                    Next = tipStep,
                },
                False = new FlowDecision()
                {
                    Condition = ExpressionServices.Convert<bool>(ctx => Guess.Get(ctx) > Target.Get(ctx)),
                    True = new FlowStep()
                    {
                        Action = new WriteLine() { Text = "猜大了，请再猜！" },
                        Next = tipStep,
                    },
                    False = new FlowStep()
                    {
                        Action = new WriteLine() { Text = "恭喜你，猜对了！" }
                    },
                }
            };
            //流程关系
            chart.StartNode = assignStep;
            assignStep.Next = tipStep;
            tipStep.Next = inputStep;
            inputStep.Next = decision;
            //启动
            WorkflowInvoker.Invoke(chart);
        }

        /// <summary>
        /// 状态机工作流
        /// </summary>
        static void StateMachineDynamic()
        {
            StateMachine machine = new StateMachine();
            //创建变量
            Variable<int> Target = new Variable<int>();
            Variable<int> Guess = new Variable<int>();
            //添加变量
            machine.Variables.Add(Target);
            machine.Variables.Add(Guess);
            //第一个State
            var assign = new Assign();
            assign.To = new OutArgument<int>(Target);//指定序列中的变量，并给它赋值
            assign.Value = new InArgument<int>(ctx => new Random().Next(1, 101));
            var assignState = new State() { Entry = assign };
            //第二个State
            var inputTip = new WriteLine() { Text = "请猜测一个1到100之间的数字：" };
            //接收输入
            var input = new GuessInput()
            {
                //Text = "动态生成节点演示-StateMachine",
                Text = new InArgument<string>(u => "动态生成节点演示-StateMachine Target=" + Target.Get(u).ToString()),
                Result = new OutArgument<int>(Guess)
            };
            var inputStep = new State() { Entry = inputTip, Exit = input };
            //第三个State
            var finalStep = new State()
            {
                IsFinal = true,
                Entry = new WriteLine() { Text = "恭喜你，猜对了！" }
            };
            //添加状态
            machine.States.Add(assignState);
            machine.States.Add(inputStep);
            machine.States.Add(finalStep);
            //设置初始化状态
            machine.InitialState = assignState;
            assignState.Transitions.Add(new Transition() { To = inputStep });
            inputStep.Transitions.Add(new Transition()
            {
                Condition = ExpressionServices.Convert<bool>(ctx => Guess.Get(ctx) == Target.Get(ctx)),
                To = finalStep,
            });
            inputStep.Transitions.Add(new Transition()
            {
                Condition = ExpressionServices.Convert<bool>(ctx => Guess.Get(ctx) < Target.Get(ctx)),
                Action = new WriteLine() { Text = "猜小了，请再猜！" },
                To = inputStep
            });
            inputStep.Transitions.Add(new Transition()
            {
                Condition = ExpressionServices.Convert<bool>(ctx => Guess.Get(ctx) > Target.Get(ctx)),
                Action = new WriteLine() { Text = "猜大了，请再猜！" },
                To = inputStep
            });
            //启动
            WorkflowInvoker.Invoke(machine);
        }

        /// <summary>
        /// 状态机工作流
        /// </summary>
        static void StateMachineDynamic2()
        {
            StateMachine machine = new StateMachine();
            //创建变量
            Variable<int> Target = new Variable<int>();
            Variable<int> Guess = new Variable<int>();
            //添加变量
            machine.Variables.Add(Target);
            machine.Variables.Add(Guess);
            //第一个State
            var assign = new Assign();
            assign.To = new OutArgument<int>(Target);//指定序列中的变量，并给它赋值
            assign.Value = new InArgument<int>(ctx => new Random().Next(1, 101));
            var assignState = new State() { Entry = assign };
            //第二个State
            var inputTip = new WriteLine() { Text = "请猜测一个1到100之间的数字：" };
            //接收输入
            var input = new GuessInput()
            {
                Text = "动态生成节点演示-StateMachine",
                //Text = new InArgument<string>(u => "动态生成节点演示-StateMachine Target=" + Target.Get(u).ToString()),
                Result = new OutArgument<int>(Guess)
            };
            var inputStep = new State() { Entry = inputTip, Exit = input };
            //第三个State
            var finalStep = new State()
            {
                IsFinal = true,
                Entry = new WriteLine() { Text = "恭喜你，猜对了！" }
            };
            //添加状态
            machine.States.Add(assignState);
            machine.States.Add(inputStep);
            machine.States.Add(finalStep);
            //设置初始化状态
            machine.InitialState = assignState;
            assignState.Transitions.Add(new Transition() { To = inputStep });
            inputStep.Transitions.Add(new Transition()
            {
                DisplayName = "Equal",
                Condition = ExpressionServices.Convert<bool>(ctx => Guess.Get(ctx) == Target.Get(ctx)),
                //Action = new WriteLine() { Text = new InArgument<string>(ctx => "相等：" + (Guess.Get(ctx) == Target.Get(ctx) ? "=" : Guess.Get(ctx) < Target.Get(ctx) ? "<" : ">")) },
                To = finalStep,
            });
            inputStep.Transitions.Add(new Transition()
            {
                Trigger = ExpressionServices.Convert<bool>(ctx => Guess.Get(ctx) != Target.Get(ctx)),
                //Action = new If()
                //{
                //    Condition = new InArgument<bool>(ctx => Guess.Get(ctx) < Target.Get(ctx)),
                //    Then = new WriteLine()
                //    {
                //        //Text = "猜小了，请再猜！"
                //        Text = new InArgument<string>(ctx => "猜小了，请再猜！Guess=" + Guess.Get(ctx).ToString() + " Target=" + Target.Get(ctx).ToString() + " " + (Guess.Get(ctx) == Target.Get(ctx) ? "=" : Guess.Get(ctx) > Target.Get(ctx) ? ">" : "<"))
                //    },
                //    Else = new WriteLine()
                //    {
                //        //Text = "猜大了，请再猜！"
                //        Text = new InArgument<string>(ctx => "猜大了，请再猜！Guess=" + Guess.Get(ctx).ToString() + " Target=" + Target.Get(ctx).ToString() + " " + (Guess.Get(ctx) == Target.Get(ctx) ? "=" : Guess.Get(ctx) > Target.Get(ctx) ? ">" : "<"))
                //    },
                //},
                To = inputStep,
            });
            //启动
            WorkflowInvoker.Invoke(machine);
        }
    }
}
